package checkers3d.presentation;

import java.awt.Color;
import java.awt.Point;

/**
 * A visible textbox GUI component. Supports component focus, the caret, and
 * security stars.
 *
 * @author Ruben Acuna
 */
public class GUITextbox extends GUIPrimitive implements IInputObserver
{
    /**
     * Flag indicating if secure text display (all *s) is on.
     */
    private boolean secure;

    /**
     * Flag indicating if the component is in focus.
     */
    private boolean focused;

    /**
     * The maximum number of characters the textbox can contain. The textbox
     * will not accept characters beyond this number.
     */
    private int maximumCharacters;

    /**
     * Actual text in the textbox.
     */
    private String text;

    /**
     * Label used to display text. Normally contains textbox text but will
     * contain *s if security is on.
     */
    private GUILabel textLabel;

    /**
     * GUI component displaying caret.
     */
    private GUIPrimitive caretPrimitive;

    /**
     * Rectangle graphic for caret.
     */
    private RenderResourceRectangle caretGraphic;

    /**
     * Class consturctor for textbox to place it a given position, with a maximum
     * number of characters, and as part of a given GUIContainer. This component
     * is automatically added to the GUIContainer.
     *
     * @param position The position of the component.
     * @param maximum Characters Maximum number of characters the textbox holds.
     * @param parent The GUIContainer this textbox exists in.
     */
    public GUITextbox(Point position, int maximumCharacters, GUIContainer parent)
    {
        //the text label is centered in the rectangle with a 2 pixel boarder.
        super(new RenderResourceRectangle(maximumCharacters * 7 + 4, 13, Color.WHITE), position);
        
        this.maximumCharacters = maximumCharacters;

        text = "";
        textLabel = new GUILabel("", Color.BLACK, new Point(position.x + 2, position.y + 2));
        caretPrimitive = new GUIPrimitive(null, position);
        caretGraphic = new RenderResourceRectangle(1, 9, Color.BLACK);

        setSecure(false);
        setFocus(false);
        updateCaret();

        parent.add(this);
        parent.add(textLabel);
        parent.add(caretPrimitive);
    }

    /**
     * Sets if a textbox should display the typed text or just stars.
     *
     * @param secure Security status.
     */
    public void setSecure(boolean secure)
    {
        this.secure = secure;
    }

    /**
     * Returns if the textbox is in focus.
     *
     * @return Focus status.
     */
    public boolean hasFocus()
    {
        return focused;
    }

    /**
     * Sets the textbox focus.
     *
     * @param focus Focus status.
     */
    public void setFocus(boolean focus)
    {
        focused = focus;

        if(focused)
            caretPrimitive.setRenderResource(caretGraphic);
        else
            caretPrimitive.setRenderResource(null);
    }

    /**
     * Updates the pixel position of the caret to be to the right of the text.
     */
    private void updateCaret()
    {
        Point position = (Point)caretPrimitive.getDrawPosition().clone();

        position.x = textLabel.getDrawPosition().x + textLabel.getWidth();
        position.y = textLabel.getDrawPosition().y;

        caretPrimitive.setDrawPosition(position);
    }

    /**
     * Returns the current text of the textbox.
     *
     * @return Label text.
     */
    public String getText()
    {
        return text;
    }

    /**
     * Sets the current text of the textbox.
     *
     * @param text Label text.
     */
    public void setText(String text)
    {
        this.text = text;
        textLabel.setText(text);
        updateCaret();
    }

    /**
    * Handles a click within a visible area.
    *
    * @param  position  Point object containing the relative coordinates of the
    *                   click.
    */
    @Override
    public void onClick(Point position)
    {
        //do nothing.
    }

    /**
    * Handles a key press, when the component has focus.
    *
    * @param  key       The character of the key that was pressed.
    * @see IInputObserver
    */
    @Override
    public void onKeyPress(char key)
    {
        int keycode = (int)key;
        
        //ASCII codes: 8 backspace, 65-90 upper case, 97-122 lower case.
        if(hasFocus())
        {
            //ASCII CODES ARE NOT MAGIC NUMBERS!!!

            //backspace
            if(keycode == UtilGUI.KEY_BACKSPACE)
            {
                if(text.length() > 0)
                    text = text.substring(0, text.length() - 1);
            }
            //upper or lower case letters, or numbers
            else if((keycode > 64 && keycode < 91) ||
                    (keycode > 96 && keycode < 123) ||
                    (keycode > 47 && keycode < 58))
            {
                //only add the character if we haven't reach the maximum length.
                if(text.length() < maximumCharacters)
                    text = text + String.valueOf(key);
            }
            //carriage return
            else if(keycode == UtilGUI.KEY_RETURN)
            {
                setFocus(false);
            }

            if(!secure)
            {
                textLabel.setText(text);
            }
            else
            {
                StringBuffer textSecured = new StringBuffer("");

                while (textSecured.length() < text.length())
                    textSecured.append("*");

                textLabel.setText(textSecured.toString());
            }

            updateCaret();
        }
    }
}